package cn.bxshey.commonModule.redis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @作者：不想说话而已
 * @Date：2023/12/4 0:20
 */

@Component
public class RedisUtils {


    private final StringRedisTemplate redisTemplate;

    private final ObjectMapper mapper;

    RedisUtils(StringRedisTemplate redisTemplate, ObjectMapper mapper) {
        this.redisTemplate = redisTemplate;
        this.mapper = mapper;
    }


    // set ******************************************************************

    /**
     * set类型  检查key中是否存在该值
     *
     * @param prefix key前缀
     * @param id     唯一标识
     * @param value  map集合参数
     */
    public <T> Boolean checkSetValue(String prefix, T id, T value) {

        return redisTemplate.opsForSet().isMember(prefix.concat(String.valueOf(id)), String.valueOf(value));
    }

    /**
     * set类型  检查key中是否存在该值
     *
     * @param id    唯一标识key
     * @param value map集合参数
     */
    public <T> Boolean checkSetValue(T id, T value) {
        String s = String.valueOf(id);
        return redisTemplate.opsForSet().isMember(s, value);
    }

    /**
     * set类型 存入单个类型的值
     *
     * @param prefix key前缀
     * @param id     唯一标识
     * @param value  map集合参数
     */
    public <T> void addSetValue(String prefix, T id, T value) throws JsonProcessingException {
        String s = String.valueOf(id);
        redisTemplate.opsForSet().add(prefix.concat(s), mapper.writeValueAsString(value));
    }

    /**
     * set类型 存入单个类型的值
     *
     * @param prefix   key前缀
     * @param id       唯一标识
     * @param value    值
     * @param timeUnit 单位：天(默认)/分钟/小时
     * @param time     有效时间
     */
    public <T> void addSetValue(String prefix, T id, T value, String timeUnit, long time) throws JsonProcessingException {
        String s = String.valueOf(id);
        redisTemplate.opsForSet().add(prefix.concat(s), mapper.writeValueAsString(value));
        setExpireTime(prefix.concat(s), timeUnit, time);
    }

    /**
     * set类型 存入单个类型的值
     *
     * @param id    唯一标识key
     * @param value 值
     */
    public <T> void addSetValue(T id, T value) throws JsonProcessingException {
        String s = String.valueOf(id);
        redisTemplate.opsForSet().add(s, mapper.writeValueAsString(value));
    }

    /**
     * set类型 存入单个类型的值
     *
     * @param id       唯一标识key
     * @param value    值
     * @param timeUnit 单位：天(默认)/分钟/小时
     * @param time     有效时间
     */
    public <T> void addSetValue(T id, T value, String timeUnit, long time) throws JsonProcessingException {
        String s = String.valueOf(id);
        redisTemplate.opsForSet().add(s, mapper.writeValueAsString(value));
        setExpireTime(s, timeUnit, time);
    }

    /**
     * set类型 存入多个类型值
     *
     * @param prefix key前缀
     * @param id     唯一标识
     * @param value  多个String值
     */
    public <T> void addSetValue(String prefix, T id, T[] value) throws JsonProcessingException {
        String s = String.valueOf(id);
        redisTemplate.opsForSet().add(prefix.concat(s), mapper.writeValueAsString(value));
    }

    /**
     * 获取指定key下的值
     *
     * @param prefix key前缀
     * @param id     唯一标识id
     * @return set集合
     */
    public <T> Set<String> getSetValue(String prefix, T id) {
        String s = String.valueOf(id);
        return redisTemplate.opsForSet().members(prefix.concat(s));
    }

    /**
     * 获取指定key下的值
     *
     * @param id 唯一标识id
     * @return set集合
     */
    public <T> Set<String> getSetValue(String id) {
        return redisTemplate.opsForSet().members(String.valueOf(id));
    }

    /**
     * 设置set类型 key存在时间
     *
     * @param key      唯一标识key
     * @param timeUnit 单位：天(默认)/分钟/小时
     * @param time     有效时间
     */
    public <T> void setExpireTime(T key, String timeUnit, long time) {
        String s = String.valueOf(key);
        switch (timeUnit) {
            case "hour":
                redisTemplate.expire(s, time, TimeUnit.HOURS);
                break;
            case "minute":
                redisTemplate.expire(s, time, TimeUnit.MINUTES);
                break;
            default:
                redisTemplate.expire(s, time, TimeUnit.DAYS);
        }
    }


    // list ******************************************************************

    /**
     * list存入单个list的值
     *
     * @param prefix key前缀
     * @param id     唯一标识
     * @param value  map集合参数
     * @return 返回list的长度
     */
    public <T> Long addSetList(String prefix, T id, T value) throws JsonProcessingException {
        String s = String.valueOf(id);
        return redisTemplate.opsForList().leftPush(prefix.concat(s), mapper.writeValueAsString(value));
    }

    /**
     * list存入单个list的值
     *
     * @param id    唯一标识
     * @param value map集合参数
     * @return 返回list的长度
     */
    public <T> Long addSetList(T id, T value) throws JsonProcessingException {
        String s = String.valueOf(id);
        return redisTemplate.opsForList().leftPush(s, mapper.writeValueAsString(value));
    }

    /**
     * 获取指定key所有list的值
     *
     * @param prefix key前缀
     * @param id     唯一标识key
     * @return 返回list<String>的value
     */
    public <T> List<String> getSetList(String prefix, T id) {
        String s = String.valueOf(id);
        return redisTemplate.opsForList().range(prefix.concat(s), 0, -1);
    }

    /**
     * 是否存在该元素。
     * @param prefix key前缀
     * @param id 唯一标识id
     * @param value 元素的值
     * @return -1则不存在，返回所在下标
     */
    public <T> Long isListValue(String prefix, T id, T value) {
        return redisTemplate.opsForList().indexOf(prefix.concat(String.valueOf(id)), String.valueOf(value));
    }


    /**
     * 删除指定与值相等的一个值值
     *
     * @param prefix key前缀
     * @param id     唯一标识id
     * @param value  需要删除的值
     * @return 删除成功了几
     */
    public <T> Long delListValue(String prefix, T id, T value) {
        return redisTemplate.opsForList().remove(prefix.concat(String.valueOf(id)), 0, String.valueOf(value));
    }

    // setHash ******************************************************************

    /**
     * 新增或修改setHash字段值
     *
     * @param prefix key前缀
     * @param id     唯一标识key
     * @param value  存入值
     * @return 该key下的字段总数
     */
    public <T> Long setHash(String prefix, T id, T value) throws JsonProcessingException {
        String s = String.valueOf(id);
        redisTemplate.opsForHash().put(prefix, s, mapper.writeValueAsString(value));
        return redisTemplate.opsForHash().size(prefix);
    }


    /**
     * 获取指定key的hash字段值
     *
     * @param prefix key前缀
     * @param id     唯一标识key
     */
    public <T> List<String> getHash(String prefix, T id) throws JsonProcessingException {
        String s = String.valueOf(id);
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(prefix.concat(s));
        Set<Object> objects = entries.keySet();
        List<String> info = new ArrayList<>();
        for (Object key : objects) {
            info.add(String.valueOf(entries.get(key)));

        }
        return info;
    }
}
